﻿// Shader-Based-Image-Processing (SBIP)
// http://code.google.com/p/sbip/
//
// Copyright © Frank Nagl, 2009-2010
// admin@franknagl.de
//
namespace SBIP.Filter
{
    using Microsoft.Xna.Framework.Graphics;
    using System;

    /// <summary>
    /// Replace RGB channel of color image.
    /// </summary>
    /// 
    /// <remarks>
    /// <para>Replaces specified RGB channel of color image with
    /// specified grayscale image.</para>
    /// 
    /// <para>The filter is quite useful in conjunction with <see cref="ExtractChannel"/> filter
    /// (however may be used alone in some cases). Using the <see cref="ExtractChannel"/> filter
    /// it is possible to extract one of RGB channel, perform some image processing with it and then
    /// put it back into the original color image.</para>
    /// 
    /// <para>Sample usage:</para>
    /// <code>
    /// // create Processor, used as rendering framework
    /// Processor processor = new Processor();
    /// // starts Processor
    /// processor.Begin(image);
    /// // create ExtractChannel filter
    /// ExtractChannel extractChannel = new ExtractChannel();
    /// processor.Filter = extractChannel;
    /// // optional: configure filter
    /// extractChannel.Channel = RGB.R;
    /// // get result texture
    /// Texture2D texture = processor.RenderToTexture();
    /// processor.ChangeTexture(texture);
    /// // create Threshold filter
    /// Threshold threshold = new Threshold();
    /// processor.Filter = threshold;
    /// // optional: configure filter
    /// threshold.Threshold = 230;
    /// texture = processor.RenderToTexture();
    /// // reset source texture to original image
    /// processor.ResetTexture();
    /// // create ReplaceChannel filter
    /// ReplaceChannel replaceChannel = new ReplaceChannel();
    /// processor.Filter = replaceChannel;
    /// // optional: configure filter
    /// replaceChannel.Channel = RGB.R;
    /// replaceChannel.ChannelTexture = texture;
    /// // apply the filter
    /// Bitmap resultImage = processor.RenderToBitmap();
    /// Texture2D resultTexture = processor.RenderToTexture( );
    /// processor.End();
    /// </code>
    /// 
    /// <para><b>Initial image:</b></para>
    /// <img src="img/shaderbased/sample1.jpg" width="480" height="361" />
    /// <para><b>Result image:</b></para>
    /// <img src="img/shaderbased/ReplaceChannel.jpg" width="480" height="361" />
    /// </remarks>
    public sealed class ReplaceChannel : BaseFilter
    {
        #region effect properties
        private short channel;
        private Texture2D channelTexture;
        /// <summary>
        /// Grayscale texture to use for channel replacement.
        /// </summary>
        /// 
        /// <remarks>
        /// <para><note>Channel texture should be grayscale image.</note></para>
        /// </remarks>      
        public Texture2D ChannelTexture
        {
            get { return channelTexture; }
            set 
            {
                channelTexture = value;
                Effect.Parameters["ChannelTexture"].SetValue(value);                
            }
        }
        
        /// <summary>RGB channel to replace.</summary>
        /// <remarks>
        /// <para>Default value is set to <see cref="SBIP.RGB.B"/>.</para>
        /// </remarks>
        /// <exception cref="ArgumentException">Invalid channel is specified.
        /// </exception>
        public short Channel
        {
            get { return channel; }
            set 
            {
                if (value != RGB.R && value != RGB.G && value != RGB.B)
                    throw new ArgumentException("Invalid channel is specified.");

                if (Effect == null)
                    throw new ArgumentException("Channel" + InitMsg);

                channel = value;
                Effect.Parameters["Channel"].SetValue(channel);
            }
        }
        #endregion effect properties

        /// <summary>
        /// Initializes a new instance of the <see cref="ReplaceChannel"/> class.
        /// </summary>
        public ReplaceChannel() : base("ReplaceChannel") { }
    }
}
